#pragma once

#include "InstanceSpecification.h"

#include "Classifier.h"
#include "Slot.h"
#include "ValueSpecification.h"

namespace uml {

InstanceSpecification::InstanceSpecification(const QString& umlType)
    : PackageableElement(umlType) {}

void InstanceSpecification::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    PackageableElement::fromJson(json, errorList);
    DeployedArtifact::fromJson(json, errorList);
    DeploymentTarget::fromJson(json, errorList);
    JsonSerializable::fromJsonArray(classifiers_, "classifiers", json, errorList);
    JsonSerializable::fromJsonArray(slots2_, "slots2", json, errorList);
    specification_ = JsonSerializable::create<ValueSpecification>(json.value("specification"), errorList);

}

void InstanceSpecification::toJson(QJsonObject& json) {
    PackageableElement::toJson(json);
    DeployedArtifact::toJson(json);
    DeploymentTarget::toJson(json);
    JsonSerializable::toJsonArray(classifiers_, "classifiers", json);
    JsonSerializable::toJsonArray(slots2_, "slots2", json);
    if (specification_) {
        QJsonObject specification_json;
        specification_->toJson(specification_json);
        json.insert("specification", specification_json);
    }
}

/// <summary>
/// classifiers getter
/// The Classifier or Classifiers of the represented instance. If multiple
/// Classifiers are specified, the instance is classified by all of them.
/// </summary>
vector<shared_ptr<Classifier>>& InstanceSpecification::classifiers() {
    return classifiers_;
}

/// <summary>
/// slots2 getter
/// A Slot giving the value or values of a StructuralFeature of the instance. An
/// InstanceSpecification can have one Slot per StructuralFeature of its
/// Classifiers, including inherited features. It is not necessary to model a Slot
/// for every StructuralFeature, in which case the InstanceSpecification is a
/// partial description.
/// </summary>
vector<shared_ptr<Slot>>& InstanceSpecification::slots2() {
    return slots2_;
}

/// <summary>
/// specification getter
/// A specification of how to compute, derive, or construct the instance.
/// </summary>
shared_ptr<ValueSpecification> InstanceSpecification::specification() const {
    return specification_;
}

/// <summary>
/// specification setter
/// A specification of how to compute, derive, or construct the instance.
/// </summary>
void InstanceSpecification::setSpecification(shared_ptr<ValueSpecification> value) {
    specification_ = value;
}

} // namespace uml
